package com.cokoyan.game.afts;

import java.util.ArrayList;
import java.util.Iterator;

import com.cokoyan.game.afts.GameView.GameThread;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

public class GraphsEnemis {

	public static enum Type{ basic, speed, strong }
	public static enum Phase{ approche, attaque }
	public static enum Direction{ descend, monte }
	
	public class Asteroid{
		public int x,y,width,height,speed;
		public Bitmap sprite;
		public boolean mDead;
		public boolean explosion;
		
		public Asteroid(Bitmap sprite, int speed){
			this.sprite = sprite;
		
			x = DATA.SPAWN_X;
			y = 30 + DATA.rnd.nextInt(240);
			width = 43;
			height = 48;
			mDead = false;
			this.speed = speed;
		}
		
		public void Update(){
			x-=speed;
		}
		
		public void Draw(Canvas canvas){
			if(!mDead)
				canvas.drawBitmap(sprite, x, y, null);
		}
	}
	
	
	public class Enemis{
		
		public class GraphsShoot{
			public int x,y,width,height,speed;
			public Bitmap sprite;
			
			public GraphsShoot(Bitmap _s,int _x, int _y){
				sprite 	= _s;
				width 	= 32;
				height 	= 16;	
				x 		= _x;
				y 		= _y+(height);
				
				speed = 5;
			}
			
			public void update(){
				x-=speed;
			}
			
			public void draw(Canvas canvas){
				canvas.drawBitmap(sprite, x, y, null);
			}
		}
		
		public int x,y,width,height;
		public int positionFinale;
		public Paint mPaint;
		public Phase mPhase;
		public Direction mDir;
		public int mVitesse;
		public boolean mDead;
		public Bitmap sprite,mSpriteShoot;
		private ArrayList<GraphsShoot> mShoots;
		private long mTimerShoot;
		private int mCadenceShoot;
		public boolean explosion;
		public Type type;
		public int live;
		public Bitmap spriteScore;
		public long timerAfficheScore;
		public boolean afficheScore;
		public Paint scorePaint;
		public int scoreAlpha;
		
		public GameThread gameThread;
		
		public Enemis(Bitmap sprite, Bitmap spriteshoot, Bitmap spriteScore, GameThread gameThread, Type t){
			this.gameThread = gameThread;
			this.sprite = sprite;
			this.spriteScore = spriteScore;
			type = t;
			afficheScore = false;
			scoreAlpha = 255;
			scorePaint = new Paint();
			scorePaint.setAlpha(scoreAlpha);
			
			x = DATA.SPAWN_X;
			y = 20+DATA.rnd.nextInt(250);
			mVitesse = DATA.rnd.nextInt(3)+DATA.getSpeedEnemyByLevel(mGameThread.mCurrentLevel);
			if(type == Type.speed){
				positionFinale = -50;
			}else{
				positionFinale = 200+DATA.rnd.nextInt(240);
			}
			
			if(type == Type.strong){
				live = 3;
			}else{
				live = 1;
			}
			
			mPaint = new Paint();
			mPaint.setColor(Color.WHITE);
			width = 48;
			height = 32;
			mPhase = Phase.approche;
			mDir = Direction.descend;
			mDead = false;
			explosion = false;
			
			mCadenceShoot = DATA.getShootCadenceByLevel(mGameThread.mCurrentLevel);
			mTimerShoot = System.currentTimeMillis();
			mSpriteShoot = spriteshoot;
			mShoots = new ArrayList<GraphsShoot>();
		}
		
		public void Draw(Canvas canvas){
			if(!mDead)
				canvas.drawBitmap(sprite,x, y,null);
			else
				canvas.drawBitmap(spriteScore,x-40, y,scorePaint);

			DrawShoots(canvas);
		}
		
		public void Update(){
			if(!mDead){
				if(type == Type.basic || type == Type.strong){
					switch(mPhase){
						case approche:{
								if(x>positionFinale) x-=4;
								else {
									mPhase = Phase.attaque;
									x=positionFinale;
								}
							break;
						}
						case attaque:{
							//Mouvement de monter/descendre
							if(y<270 && mDir==Direction.descend){
								y+=mVitesse;
								if(y>=270){
									mDir = Direction.monte;
								}
							}else if(y>20 && mDir==Direction.monte){
								y-=mVitesse;
								if(y<=20){
									mDir = Direction.descend;
								}
							}
							break;
						}
					}
				}else if(type == Type.speed){
					if(y<270 && mDir==Direction.descend){
						y+=mVitesse;
						if(y>=270){
							mDir = Direction.monte;
						}
					}else if(y>20 && mDir==Direction.monte){
						y-=mVitesse;
						if(y<=20){
							mDir = Direction.descend;
						}
					}
					if(x>positionFinale) x-=5;
					else {
						x=positionFinale;
						this.mDead = true;
					}
				}
			}else{
				if(mDead && System.currentTimeMillis()>=timerAfficheScore+700){
					afficheScore = false;
				}else{
					scoreAlpha-= 20;
					if(scoreAlpha<0) scoreAlpha = 0;
					scorePaint.setAlpha(scoreAlpha);
				}
			}
			this.UpdateShoots();
		}
		
		
		public void UpdateShoots(){
			if(!mDead && System.currentTimeMillis()>=mTimerShoot+mCadenceShoot){
				mTimerShoot = System.currentTimeMillis();
				mCadenceShoot = DATA.getShootCadenceByLevel(mGameThread.mCurrentLevel);
				this.CreateShoot();
			}
			try{
				Iterator<GraphsShoot> it = mShoots.iterator();
				while(it.hasNext()){
					GraphsShoot gs = it.next();
					gs.update();
					if(gs.x<=-20){
						it.remove();
					}else{
						//Detection du tire sur le joueur :)
						/*if(gs.x+10>mGameThread.mXPlayer-5 && gs.x+10<mGameThread.mXPlayer+48+5){
							if(gs.y+5>mGameThread.mYPlayer-5 && gs.y+5<mGameThread.mYPlayer+32+5){*/
						if(DATA.isCollided(gs.x, gs.y, gs.width, gs.height, mGameThread.mXPlayer, mGameThread.mYPlayer, 48, 32)){
								//mort du joueur
								it.remove();
								if(!mGameThread.playerShielded()){
									mGameThread.mSounds.playSound(GameSounds.SOUND_EXPLOSION);
									mGameThread.killPlayer();
								}else{
									mGameThread.mSounds.playSound(GameSounds.SOUND_SHOOT2);
								}
							//}
						}
						
						//Detection du tire sur un asteroid
						Iterator<Asteroid> itAsteroid = mAsteroidList.iterator();
						while(itAsteroid.hasNext()){
							Asteroid a = itAsteroid.next();
							if(a!=null){
								if(DATA.isCollided(gs.x, gs.y, gs.width, gs.height, a.x, a.y, a.width, a.height)){
									//this.explosion.add(new SpriteAnimated(sImpact,gs.x,gs.y,30,30,5,50));
									mGameThread.mSounds.playSound(GameSounds.SOUND_SHOOT2);
									it.remove();
								}
							}
						}
					}
				}
				
			}catch(Exception e){
				
			}
		}
		
		public void CreateShoot(){
			GraphsShoot gs = new GraphsShoot(mSpriteShoot,x-width,y-height/2);
			mShoots.add(gs);
			mGameThread.mSounds.playSound(GameSounds.SOUND_SHOOT);
		}
		
		public void DrawShoots(Canvas canvas){
			try{
				Iterator<GraphsShoot> it = mShoots.iterator();
				while(it.hasNext()){
					GraphsShoot gs = it.next();
					if(gs!=null)
						gs.draw(canvas);
				}
			}catch(Exception e){
				
			}
		}
	}
	
	private ArrayList<Enemis> mEnemis;
	public ArrayList<SpriteAnimated> explosion;
	public Bitmap []sExplosion;
	private Bitmap mSpriteEnemis;
	private Bitmap mSpriteEnemis2;
	private Bitmap mSpriteEnemis3;
	private Bitmap mSpriteShoot;
	private Bitmap mSpriteScore;
	
	private boolean mAllDied;
	private GameThread mGameThread;
	

	public class Bonus{
		public long mTimerBonus;
		public int mBonusType;
		public int xBonus, yBonus;
		public Bitmap mBonus;
		
		public Bitmap spriteScore;
		public long timerAfficheScore;
		public boolean afficheScore;
		public Paint scorePaint;
		public int scoreAlpha;
		public boolean hited;
		
		public Bonus(Bitmap spriteScore){
			this.spriteScore = spriteScore;
			afficheScore = false;
			hited = false;
			scoreAlpha = 255;
			scorePaint = new Paint();
			scorePaint.setAlpha(scoreAlpha);
		}
		
		public void Draw(Canvas canvas){
			if(afficheScore && mBonusType<3){
				canvas.drawBitmap(spriteScore, xBonus, yBonus, scorePaint);
			}else if(!hited){
				canvas.drawBitmap(mBonus, xBonus, yBonus, null);
			}
		}
		
		public void Update(){
			if(afficheScore && mBonusType<3){
				scoreAlpha-=20;
				if(scoreAlpha<0)scoreAlpha=0;
				scorePaint.setAlpha(scoreAlpha);
				if(System.currentTimeMillis()>=timerAfficheScore+700){
					afficheScore = false;
				}
			}else{
				xBonus -= 10;
			}
		}
	}
	
	public Bitmap mBonusScore1,
	mBonusScore2,mBonusScore3,
	mBonusPower, mBonusShield, mBonusShootP, mBonusShootW, mBonusScore100, mBonusScore200, mBonusScore300;
	private ArrayList<Bonus> mBonusList;
	private ArrayList<Asteroid> mAsteroidList;
	private Bitmap mAsteroidSprite;
	private long mAsteroidTimer;
	private boolean FirstRunning;
	
	public GraphsEnemis(Context context, GameThread gameThread){
		mGameThread = gameThread;
		initVar();
		
		Bitmap sprites = GraphsSprite.loadSemiBitmap(context.getResources().getDrawable(R.drawable.monsters));
		mSpriteEnemis = Bitmap.createBitmap(sprites,0,0,48,32);
		mSpriteEnemis2 = Bitmap.createBitmap(sprites,48,0,48,32);
		mSpriteEnemis3 = Bitmap.createBitmap(sprites,96,0,48,32);
		
		mSpriteShoot = GraphsSprite.loadSemiBitmap(context.getResources().getDrawable(R.drawable.shoot01));
		
		Bitmap spritesScores = GraphsSprite.loadSemiBitmap(context.getResources().getDrawable(R.drawable.score));
		mSpriteScore = Bitmap.createBitmap(spritesScores,0,0,80,30);
		mBonusScore100 = Bitmap.createBitmap(spritesScores,80,0,80,30);
		mBonusScore200 = Bitmap.createBitmap(spritesScores,160,0,80,30);
		mBonusScore300 = Bitmap.createBitmap(spritesScores,240,0,80,30);
		
		Bitmap spritesBonus = GraphsSprite.loadSemiBitmap(context.getResources().getDrawable(R.drawable.bonus));
		mBonusScore1 = Bitmap.createBitmap(spritesBonus,0,0,30,30);
		mBonusScore2 = Bitmap.createBitmap(spritesBonus,30,0,30,30);
		mBonusScore3 = Bitmap.createBitmap(spritesBonus,60,0,30,30);
		mBonusPower = Bitmap.createBitmap(spritesBonus,90,0,30,30);
		mBonusShield = Bitmap.createBitmap(spritesBonus,120,0,30,30);
		mBonusShootP = Bitmap.createBitmap(spritesBonus,150,0,30,30);
		mBonusShootW = Bitmap.createBitmap(spritesBonus,180,0,30,30);
		
		mAsteroidSprite = GraphsSprite.loadSemiBitmap(context.getResources().getDrawable(R.drawable.asteroid));
		
		Bitmap theExplosion = GraphsSprite.loadSemiBitmap(context.getResources().getDrawable(R.drawable.sprite_explode));
		sExplosion = new Bitmap[16];
		for(int i=0;i<16;i++){
			sExplosion[i] = Bitmap.createBitmap(theExplosion, 75*i, 0, 75, 95);
		}
	}
	
	public void initVar(){
		mEnemis = new ArrayList<Enemis>();
		explosion = new ArrayList<SpriteAnimated>();
		mBonusList = new ArrayList<Bonus>();
		mAsteroidList  = new ArrayList<Asteroid>();
		mAllDied = false;
		FirstRunning = true;
	}
	
	public void spawnBonus(){
		
		switch(DATA.rnd.nextInt(7)){
			case 0:{
				Bonus bonus = new Bonus(mBonusScore100);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 0;
				bonus.mBonus = mBonusScore1;
				mBonusList.add(bonus);
				break;
			}
			case 1:{
				Bonus bonus = new Bonus(mBonusScore200);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 1;
				bonus.mBonus = mBonusScore2;
				mBonusList.add(bonus);
				break;
			}
			case 2:{
				Bonus bonus = new Bonus(mBonusScore300);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 2;
				bonus.mBonus = mBonusScore3;
				mBonusList.add(bonus);
				break;
			}
			case 3:{
				Bonus bonus = new Bonus(mSpriteScore);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 3;
				bonus.mBonus = mBonusPower;
				mBonusList.add(bonus);
				break;
			}
			case 4:{
				Bonus bonus = new Bonus(mSpriteScore);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 4;
				bonus.mBonus = mBonusShield;
				mBonusList.add(bonus);
				break;
			}
			case 5:{
				Bonus bonus = new Bonus(mSpriteScore);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 5;
				bonus.mBonus = mBonusShootP;
				mBonusList.add(bonus);
				break;
			}
			case 6:{
				Bonus bonus = new Bonus(mSpriteScore);
				bonus.xBonus = DATA.SPAWN_X;
				bonus.yBonus = 30+DATA.rnd.nextInt(240);
				bonus.mBonusType = 6;
				bonus.mBonus = mBonusShootW;
				mBonusList.add(bonus);
				break;
			}
		}
		
	}
	
	public void SpawnAsteroid(){
		Asteroid a = new Asteroid(mAsteroidSprite, DATA.getAsteroidSpeed(mGameThread.mCurrentLevel));
		mAsteroidList.add(a);
	}
	
	public void SpawnEnemy(Type t, int number){
		mGameThread.mCurrentLevel++;
		this.spawnBonus();
		for(int i=0; i<number;i++){
			if(DATA.getEnemyType(mGameThread.mCurrentLevel)==Type.basic){
				Enemis e = new Enemis(mSpriteEnemis, mSpriteShoot, mSpriteScore, mGameThread, Type.basic);
				mEnemis.add(e);
			}else if(DATA.getEnemyType(mGameThread.mCurrentLevel)==Type.speed){
				Enemis e = new Enemis(mSpriteEnemis2, mSpriteShoot, mSpriteScore, mGameThread, Type.speed);
				mEnemis.add(e);
			}else if(DATA.getEnemyType(mGameThread.mCurrentLevel)==Type.strong){
				Enemis e = new Enemis(mSpriteEnemis3, mSpriteShoot, mSpriteScore, mGameThread, Type.strong);
				mEnemis.add(e);
			}
		}
		mAllDied = false;
	}
	
	public boolean getAllDied() {
		return mAllDied;
	}
	
	public ArrayList<Enemis> getEnemisList(){
		return mEnemis;
	}
	
	public ArrayList<Bonus> getBonusList(){
		return mBonusList;
	}
	
	public void UpdateEnemis(){
		
			try{
				Iterator<Enemis> it = mEnemis.iterator();
				if(!it.hasNext() && mGameThread.mControl){
					mAllDied = true;
					SpawnEnemy(Type.basic, DATA.getNbEnemisByLevel(mGameThread.mCurrentLevel));
				}
				while(it.hasNext()){
					Enemis e = it.next();
					if(e!=null){
						if(e.mDead && !e.explosion){
							e.explosion = true;
							explosion.add(new SpriteAnimated(sExplosion,e.x,e.y,75,95,16,50));
							//it.remove();
						}if(e.mDead && e.mShoots.isEmpty() && !e.afficheScore){
							it.remove();
						}
						e.Update();
					}
				}
			}catch(Exception e){
				
			}
		
	}
	
	public void UpdateBonus(){
			try{
				Iterator<Bonus> it = mBonusList.iterator();
				while(it.hasNext()){
					Bonus bonus = it.next();
					bonus.Update();
					if(bonus.xBonus<-30){
						it.remove();
					}
				}
			}catch(Exception e){
				
			}
		
	}
	
	public void UpdateAsteroids(){
		if(mGameThread.mControl && FirstRunning){
			mAsteroidTimer = System.currentTimeMillis();
			FirstRunning = false;
		}
		
		if(mGameThread.mControl){
			if(System.currentTimeMillis()>=mAsteroidTimer+DATA.getAsteroidRespawnCadence(mGameThread.mCurrentLevel)){
				this.SpawnAsteroid();
				mAsteroidTimer = System.currentTimeMillis();
			}
		}
		
		try{
			Iterator<Asteroid> it = mAsteroidList.iterator();
			while(it.hasNext()){
				Asteroid a = it.next();
				if(a.mDead && !a.explosion){
					a.explosion = true;
					explosion.add(new SpriteAnimated(sExplosion,a.x,a.y,75,95,16,50));
					it.remove();
				}else{
					a.Update();
					if(a.x<-50){
						it.remove();
					}
				}
			}
		}catch(Exception e){
			
		}
	}
	
	public void DrawEnemis(Canvas canvas){
		try{
			Iterator<SpriteAnimated> itE = this.explosion.iterator();
			while(itE.hasNext()){
				SpriteAnimated ex = itE.next();
				if(ex.isFinish()){
					itE.remove();
				}else{
					ex.Draw(canvas);
				}
			}
			
			Iterator<Enemis> it = mEnemis.iterator();
			while(it.hasNext()){
				Enemis e = it.next();
				if(e!=null)
					e.Draw(canvas);
			}
		}catch(Exception e){
			
		}
	}
	
	public void DrawBonus(Canvas canvas){
		Iterator<Bonus> it = mBonusList.iterator();
		while(it.hasNext()){
			Bonus bonus = it.next();
			bonus.Draw(canvas);
		}
	}
	
	public void DrawAsteroids(Canvas canvas){
		Iterator<Asteroid> it = mAsteroidList.iterator();
		while(it.hasNext()){
			Asteroid a = it.next();
			a.Draw(canvas);
		}
	}
	
	public void restart(){
		initVar();
	}

	public ArrayList<Asteroid> getAsteroids() {
		return mAsteroidList;
	}
}
